﻿using System;
using Glue;
using Xunit;

namespace GlueTests.RelationContainerTests
{
    public class When_handling_both_nested_mappings_and_nested_simplified_relations
    {
        private readonly Mapping<DomainPerson, GuiPerson> mapping;

        public class DomainPerson
        {
            public DomainAddress Address { get; set; }
            public DomainAddress SecondaryAddress { get; set; }
        }
        
        public class DomainAddress
        {
            public String City { get; set; }
            public String ZipCode { get; set; }
        }

        public class GuiPerson
        {
            public GuiAddress Address { get; set; }
            public GuiAddress SecondaryAddress { get; set; }
        }

        public class GuiAddress
        {
            public String City { get; set; }
            public String ZipCode { get; set; }
        }

        public When_handling_both_nested_mappings_and_nested_simplified_relations()
        {
            mapping = new Mapping<DomainPerson, GuiPerson>();
        }

        [Fact]
        public void Should_not_allow_on_same_base_property()
        {
            mapping.Relate(domain=>domain.Address,gui=>gui.Address,GetAddressMapping());
            Assert.Throws<GlueException>(() =>
                       mapping.Relate(domain => domain.Address.City, gui => gui.Address.City)
                );
        }

        [Fact]
        public void Should_not_allow_on_same_base_property_TowardsLeft()
        {
            mapping.Relate(domain => domain.Address, gui => gui.Address, GetAddressMapping());
            Assert.Throws<GlueException>(() =>
                       mapping.RelateTowardsLeft(domain => domain.Address.City, gui => gui.Address.City)
                );
        }

        [Fact]
        public void Should_not_allow_on_same_base_property_TowardsRight()
        {
            mapping.Relate(domain => domain.Address, gui => gui.Address, GetAddressMapping());
            Assert.Throws<GlueException>(() =>
                       mapping.RelateTowardsRight(domain => domain.Address.City, gui => gui.Address.City)
                );
        }

        [Fact]
        public void Should_not_allow_on_same_base_property_reverse()
        {
            mapping.Relate(domain => domain.Address.City, gui => gui.Address.City);
            Assert.Throws<GlueException>(() =>
                       mapping.Relate(domain => domain.Address, gui => gui.Address, GetAddressMapping())
                );
        }

        [Fact]
        public void Should_not_allow_on_same_base_property_even_when_different_sub_properties()
        {
            mapping.Relate(domain => domain.Address, gui => gui.Address, GetAddressMapping());
            Assert.Throws<GlueException>(() =>
                       mapping.Relate(domain => domain.Address.ZipCode, gui => gui.Address.ZipCode)
                );
        }

        [Fact]
        public void Should_allow_on_different_properties()
        {
            mapping.Relate(domain => domain.Address.ZipCode, gui => gui.Address.ZipCode);
            mapping.Relate(domain => domain.SecondaryAddress,gui=>gui.SecondaryAddress,GetAddressMapping());
        }

        private Mapping<DomainAddress,GuiAddress> GetAddressMapping()
        {
            var addressMapping = new Mapping<DomainAddress, GuiAddress>();
            addressMapping.Relate(domain => domain.City, gui => gui.City);
            return addressMapping;
        }
    }
}
